package org.lc.solon.cmd.plugin;

import org.lc.solon.cmd.CmdBuilder;
import org.lc.solon.cmd.Command;
import org.lc.solon.cmd.SolonCommandRegistry;
import org.lc.solon.cmd.TypedDataCompleter;
import org.lc.solon.cmd.impl.DefaultCmdBuilder;
import org.lc.solon.cmd.impl.DefaultSolonCommandRegistry;
import org.lc.solon.cmd.impl.completer.CompleterManager;
import org.lc.solon.cmd.plugin.anno.Cmd;
import org.lc.solon.cmd.util.CollectionUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.AopContext;
import org.noear.solon.core.Plugin;
import org.noear.solon.core.event.AppLoadEndEvent;
import org.noear.solon.core.event.EventBus;
import org.noear.solon.core.event.EventListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.LogManager;

@Component
public class CmdPlugin implements Plugin, EventListener<AppLoadEndEvent> {

    SolonCommandRegistry registry = DefaultSolonCommandRegistry.getInstance();

    CmdBuilder cmdBuilder = new DefaultCmdBuilder();

    private static final Map<Class<?>, List<Command>> commands = new HashMap<>();

    @Override
    public void start(AopContext context) throws Throwable {
        LogManager.getLogManager().readConfiguration(CmdPlugin.class.getResourceAsStream("/logging.properties"));
        context.beanBuilderAdd(Cmd.class, ((clz, bw, anno) -> {
            List<Command> cmdList = cmdBuilder.buildCommands(clz);
            if (CollectionUtil.isNotEmpty(cmdList)) {
                synchronized (this) {
                    commands.put(clz, cmdList);
                }
            }
        }));
        Command.Config config = new Command.Config();
        config.setIgnoreUnknownOpt(true);
        EventBus.subscribe(AppLoadEndEvent.class, this);
        context.subBeansOfType(TypedDataCompleter.class, bean -> CompleterManager.registerCompleter(bean.accept(),
                bean));
        context.beanScan("org.lc.solon.cmd.plugin.scan");
    }

    @Override
    public void onEvent(AppLoadEndEvent appLoadEndEvent) {
        synchronized (this) {
            if (CollectionUtil.isNotEmpty(commands)) {
                List<Command> commandList = new ArrayList<>(commands.size());
                commands.forEach((k, v) -> commandList.addAll(v));
                registry.registerCommands(commandList);
            }
        }
    }
}
